﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace LightCAD.Core
{
    [Flags]
    public enum DirtyType 
    {
        None = 0,
        Add,
        Change,
        Delete
    }
    public abstract class ModelObject:LcObject
    {
        public string Uuid { get; set; }
        public string Name { get; set; }
        public Transform3d Transform { get; protected set; }=new Transform3d();
        public Matrix4 WorldMatrix { get; protected set; } = new Matrix4();
        public void UpdateWorldMatrix ()
        {
            var parentMatrix = (this.Parent as ModelObject)?.WorldMatrix;
            if (parentMatrix != null && !parentMatrix.IsIdentity())
            {
                this.WorldMatrix.MultiplyMatrices(parentMatrix,this.Transform.Matrix);
            }
            else
                this.WorldMatrix.Copy(this.Transform.Matrix);
           
        }
     
    }
   
    public class ModelSpace :ModelObject
    {

        public ListEx<ModelArea> Areas { get; }=new ListEx<ModelArea>();

        public ModelSpace AddAreas(params ModelArea[] areas)
        {
            foreach (var a in areas)
            {
                a.Parent = this;
                this.Areas.Add(a);
            }
            return this;
        }
    }
    public class ModelArea : ModelObject
    {
        public ListEx<ModelSite> Sites { get; }=new ListEx<ModelSite>();
        public ModelArea AddSites(params ModelSite[] sites)
        {
            foreach (var s in sites)
            {
                s.Parent = this;
                this.Sites.Add(s);
            }
            return this;
        }
    }

    public class ModelSite :ModelObject
    {
        public virtual ListEx<ModelGroup> Groups { get; } = new ListEx<ModelGroup>();
        public virtual ModelSite AddGroups(params ModelGroup[] groups)
        {
            foreach (var g in groups)
            {
                g.Parent = this;
                this.Groups.Add(g);
            }
            return this;
        }
    }
    public class ModelGroup : ModelObject
    {
        public ListEx<ModelNode> Nodes { get; } = new ListEx<ModelNode>();

        public ListEx<ModelGroup> Groups { get; } = new ListEx<ModelGroup>();
        public virtual ModelGroup AddGroups(params ModelGroup[] groups)
        {
            foreach (var g in groups)
            {
                g.Parent = this;
                this.Groups.Add(g);
                g.DirtyType = DirtyType.Add;
            }
            return this;
        }

        public virtual ModelGroup AddNodes(params ModelNode[] nodes)
        {
            foreach (var n in nodes)
            {
                n.Parent = this;
                this.Nodes.Add(n);
                n.DirtyType = DirtyType.Add;
            }
            return this;
        }

        public virtual ModelGroup RemoveGroups(params ModelGroup[] groups)
        {
            for (int i = 0; i < groups.Length; i++)
            {
                groups[i].Parent = null;
                this.Groups.Remove(groups[i]);
            }
            return this;
        }

        public virtual ModelGroup ClearGroups()
        {
            this.Groups.ForEach(g => g.Parent = null);
            this.Groups.Clear();
            return this;
        }

        public virtual ModelGroup RemoveNodes(params ModelNode[] nodes)
        {
            for (int i = 0; i < nodes.Length; i++)
            {
                nodes[i].Parent = null;
                this.Nodes.Remove(nodes[i]);
            }
            return this;
        }

        public virtual ModelGroup ClearNodes()
        {
            this.Nodes.ForEach(n => n.Parent = null);
            this.Nodes.Clear();
            return this;
        }
    }
    public class ModelNode : ModelObject
    {
        public IComponentInstance Component { get; set; }
    }
}
